package pacman.protocol;

import java.io.IOException;
import java.util.ArrayList;

import maze.Coordinate;
import maze.Location;
import pacman.Game;
import robots.Ghost;
import robots.OwnGhost;

import bluetoothCommunication.Config;

import com.rabbitmq.client.Channel;

public class GhostProtocolSender {
	private OwnGhost ghost;
	private Channel channel;
	
	private ArrayList<String> sendDISCOVERs=new ArrayList<String>();
	private ArrayList<String> sendBARCODEs=new ArrayList<String>();
	private String lastPOSITIONsend;
	
	protected boolean lastOneToSendPacman;
	private String lastPACMANsend;
	
	public GhostProtocolSender(OwnGhost ghost){
		this.ghost = ghost;
		setSendDISCOVERs(new ArrayList<String>(Game.NUMBEROFGHOSTS));
		setSendBARCODEs(new ArrayList<String>(Game.NUMBEROFGHOSTS));
		lastOneToSendPacman = false;
		if(ghost.getGame()!=null)
			channel = ghost.getGame().getChannel();
	}
	
	public void sendJOIN(){
		String message = "JOIN\n";
		if (channel != null){
			try{
				channel.basicPublish(Config.EXCHANGE_NAME, "", null, message.getBytes());
			} catch(IOException e){
				System.err.println("Problem sending following message: " + message);
			}
		}
	}

	public void sendNAME(){
		//Naam geen 2 keer verzenden
		if(!ghost.hasSendName){
			String message = ghost.getName() + " NAME " + "2.2\n";
			if (channel != null){
				try{
					channel.basicPublish(Config.EXCHANGE_NAME, "", null, message.getBytes());
				} catch(IOException e){
					System.err.println("Problem sending following message: " + message);
				}
			}
		}
		ghost.setSendName(true);
	}
	
	public void sendRENAME(){
		String message = ghost.getName() + " RENAME " + "2.2\n";
		if (channel != null){
			try{
				channel.basicPublish(Config.EXCHANGE_NAME, "", null, message.getBytes());
			} catch(IOException e){
				System.err.println("Problem sending following message: " + message);
			}
		}
	}

	public void sendPOSITION(){
		String message = ghost.getName() + " POSITION "
				+ ghost.getMaze().getCoordinateOfLocation(ghost.getLocation()).toString()
				+ "\n";
		if (channel != null){
			try{
				channel.basicPublish(Config.EXCHANGE_NAME, "", null, message.getBytes());
			} catch(IOException e){
				System.err.println("Problem sending following message: " + message);
			}
		}
		lastPOSITIONsend = message;
	}

	public void sendDISCOVER(int n, int o, int z, int w){
		String message = ghost.getName() + " DISCOVER " + ghost.getMaze().getCoordinateOfLocation(ghost.getLocation()).toString() + " " + n + " " + o + " " + z + " " + w + "\n";
		if (channel != null){
			try{
				channel.basicPublish(Config.EXCHANGE_NAME, "", null, message.getBytes());
			} catch(IOException e){
				System.err.println("Problem sending following message: " + message);
			}
		}
		sendDISCOVERs.add(message);
	}
	
	public void sendBARCODEAT(Coordinate ownCoordinate, int code, int direction){
		if (code == 0)
			return;
		String message = ghost.getName() + " BARCODEAT " + ownCoordinate.getX() + "," + ownCoordinate.getY() + " " + code + " " + direction + "\n";
		if (channel != null){
			try{
				channel.basicPublish(Config.EXCHANGE_NAME, "", null, message.getBytes());
			} catch(IOException e){
				System.err.println("Problem sending following message: " + message);
			}
		}
		sendBARCODEs.add(message);

 	}
	
	public void sendUNDOBARCODE(Coordinate coordinate){
		String message = ghost.getName() + " UNDOBARCODE " + coordinate.getX() + "," + coordinate.getY() + "\n";
		if (channel != null){
			try{
				channel.basicPublish(Config.EXCHANGE_NAME, "", null, message.getBytes());
			} catch(IOException e){
				System.err.println("Problem sending following message: " + message);
			}
		}
		//Remove the barcode from the list of barcodes sent
		for(String barcodeMsg: sendBARCODEs){
			if(barcodeMsg.matches(coordinate.getX() + "," + coordinate.getY())){
				sendBARCODEs.remove(barcodeMsg);
				break;
			}
		}
 	}
	
	public void sendPACMAN(Coordinate coord){
		String message = ghost.getName() + " PACMAN " + coord.toString() + "\n";
		if (channel != null){
			try{
				channel.basicPublish(Config.EXCHANGE_NAME, "", null, message.getBytes());
			} catch(IOException e){
				System.err.println("Problem sending following message: " + message);
			}
		}
		lastPACMANsend = message;
	}
	
	public void sendPLAN(ArrayList<Location> plan){
		String message = ghost.getName() + " PLAN";
		for(Location loc: plan){
			message += " " + loc.toString();
		}
		message += "\n";
		if (channel != null){
			try{
				channel.basicPublish(Config.EXCHANGE_NAME, "", null, message.getBytes());
			} catch(IOException e){
				System.err.println("Problem sending following message: " + message);
			}
		}
	}
	
	public void sendCANCELPLAN(){
		String message = ghost.getName() + " CANCELPLAN\n";
		if (channel != null){
			try{
				channel.basicPublish(Config.EXCHANGE_NAME, "", null, message.getBytes());
			} catch(IOException e){
				System.err.println("Problem sending following message: " + message);
			}
		}
	}
	
	public void sendPING(String destination, String string){
		String message = ghost.getName() + " PING " + destination + " " + string + "\n";
		if (channel != null){
			try{
				channel.basicPublish(Config.EXCHANGE_NAME, "", null, message.getBytes());
			} catch(IOException e){
				System.err.println("Problem sending following message: " + message);
			}
		}
		if(destination.equals("*")){
			for(Ghost g: getGame().getOtherGhostsThan(ghost.getName())){
				ghost.getWaitingForPONG().add(g);
			}
		}else{
			if(getGame().getGhostWithName(destination) != null){ //Niet wachten op de pong van een onbestaande robot
				ghost.getWaitingForPONG().add(getGame().getGhostWithName(destination));
			}
		}
	}
	
	public void sendPONG(String destination, String string){
		String message = ghost.getName() + " PONG " + destination + " " + string + "\n";
		if (channel != null){
			try{
				channel.basicPublish(Config.EXCHANGE_NAME, "", null, message.getBytes());
			} catch(IOException e){
				System.err.println("Problem sending following message: " + message);
			}
		}
	}
	
	public void sendSHOWMAP(String destination){
		String message = ghost.getName() + " SHOWMAP " + destination + "\n";
		if (channel != null){
			try{
				channel.basicPublish(Config.EXCHANGE_NAME, "", null, message.getBytes());
			} catch(IOException e){
				System.err.println("Problem sending following message: " + message);
			}
		}
	}
	
	/**
	 * Sends a message that has already been formatted and is guaranteed to be a valid protocol message.
	 * Should currently only be used by the OwnGhostProtocolProcessor
	 */
	protected void sendPreProcessedMessage(String message){
		if (channel != null){
			try{
				channel.basicPublish(Config.EXCHANGE_NAME, "", null, message.getBytes());
			} catch(IOException e){
				System.err.println("Problem sending following message: " + message);
			}
		}
	}

	protected ArrayList<String> getSendDISCOVERs() {
		return sendDISCOVERs;
	}
	private void setSendDISCOVERs(ArrayList<String> sendDISCOVERs) {
		this.sendDISCOVERs = sendDISCOVERs;
	}

	protected ArrayList<String> getSendBARCODEs() {
		return sendBARCODEs;
	}
	private void setSendBARCODEs(ArrayList<String> sendBARCODEs) {
		this.sendBARCODEs = sendBARCODEs;
	}

	protected String getLastPOSITIONsend() {
		return lastPOSITIONsend;
	}
	private void setLastPOSITIONsend(String lastPOSITIONsend) {
		this.lastPOSITIONsend = lastPOSITIONsend;
	}

	protected String getLastPACMANsend() {
		return lastPACMANsend;
	}
	private void setLastPACMANsend(String lastPACMANsend) {
		this.lastPACMANsend = lastPACMANsend;
	}

	private Game getGame() {
		return ghost.getGame();
	}

}
